use crate::src::struct_and_type::{HashTableValueFreeFunc, HashTableKey, HashTablePair, HashTableKeyFreeFunc, HashTableEqualFunc, HashTableHashFunc, HashTable, _HashTable, HashTableIterator, _HashTablePair, _HashTableIterator, _HashTableEntry, HashTableEntry, HashTableValue};
use ::libc;
extern "C" {
    fn malloc(_: u64) -> *mut libc::c_void;
    fn calloc(_: u64, _: u64) -> *mut libc::c_void;
    fn free(_: *mut libc::c_void);
}
static mut hash_table_primes: [u32; 24] = [
    193 as i32 as u32,
    389 as i32 as u32,
    769 as i32 as u32,
    1543 as i32 as u32,
    3079 as i32 as u32,
    6151 as i32 as u32,
    12289 as i32 as u32,
    24593 as i32 as u32,
    49157 as i32 as u32,
    98317 as i32 as u32,
    196613 as i32 as u32,
    393241 as i32 as u32,
    786433 as i32 as u32,
    1572869 as i32 as u32,
    3145739 as i32 as u32,
    6291469 as i32 as u32,
    12582917 as i32 as u32,
    25165843 as i32 as u32,
    50331653 as i32 as u32,
    100663319 as i32 as u32,
    201326611 as i32 as u32,
    402653189 as i32 as u32,
    805306457 as i32 as u32,
    1610612741 as i32 as u32,
];
static mut hash_table_num_primes: u32 = 0;
unsafe extern "C" fn hash_table_allocate_table(
    mut hash_table: *mut HashTable,
) -> i32 {
    let mut new_table_size: u32 = 0;
    if (*hash_table).prime_index < hash_table_num_primes {
        new_table_size = hash_table_primes[(*hash_table).prime_index as usize];
    } else {
        new_table_size = ((*hash_table).entries)
            .wrapping_mul(10 as i32 as u32);
    }
    (*hash_table).table_size = new_table_size;
    (*hash_table)
        .table = calloc(
        (*hash_table).table_size as u64,
        ::core::mem::size_of::<*mut HashTableEntry>() as u64,
    ) as *mut *mut HashTableEntry;
    return ((*hash_table).table != 0 as *mut libc::c_void as *mut *mut HashTableEntry)
        as i32;
}
unsafe extern "C" fn hash_table_free_entry(
    mut hash_table: *mut HashTable,
    mut entry: *mut HashTableEntry,
) {
    let mut pair: *mut HashTablePair = 0 as *mut HashTablePair;
    pair = &mut (*entry).pair;
    if ((*hash_table).key_free_func).is_some() {
        ((*hash_table).key_free_func).expect("non-null function pointer")((*pair).key);
    }
    if ((*hash_table).value_free_func).is_some() {
        ((*hash_table).value_free_func)
            .expect("non-null function pointer")((*pair).value);
    }
    free(entry as *mut libc::c_void);
}
#[no_mangle]
pub unsafe extern "C" fn hash_table_new(
    mut hash_func: HashTableHashFunc,
    mut equal_func: HashTableEqualFunc,
) -> *mut HashTable {
    let mut hash_table: *mut HashTable = 0 as *mut HashTable;
    hash_table = malloc(::core::mem::size_of::<HashTable>() as u64)
        as *mut HashTable;
    if hash_table.is_null() {
        return 0 as *mut HashTable;
    }
    (*hash_table).hash_func = hash_func;
    (*hash_table).equal_func = equal_func;
    (*hash_table).key_free_func = None;
    (*hash_table).value_free_func = None;
    (*hash_table).entries = 0 as i32 as u32;
    (*hash_table).prime_index = 0 as i32 as u32;
    if hash_table_allocate_table(hash_table) == 0 {
        free(hash_table as *mut libc::c_void);
        return 0 as *mut HashTable;
    }
    return hash_table;
}
#[no_mangle]
pub unsafe extern "C" fn hash_table_free(mut hash_table: *mut HashTable) {
    let mut rover: *mut HashTableEntry = 0 as *mut HashTableEntry;
    let mut next: *mut HashTableEntry = 0 as *mut HashTableEntry;
    let mut i: u32 = 0;
    i = 0 as i32 as u32;
    while i < (*hash_table).table_size {
        rover = *((*hash_table).table).offset(i as isize);
        while !rover.is_null() {
            next = (*rover).next;
            hash_table_free_entry(hash_table, rover);
            rover = next;
        }
        i = i.wrapping_add(1);
        i;
    }
    free((*hash_table).table as *mut libc::c_void);
    free(hash_table as *mut libc::c_void);
}
#[no_mangle]
pub unsafe extern "C" fn hash_table_register_free_functions(
    mut hash_table: *mut HashTable,
    mut key_free_func: HashTableKeyFreeFunc,
    mut value_free_func: HashTableValueFreeFunc,
) {
    (*hash_table).key_free_func = key_free_func;
    (*hash_table).value_free_func = value_free_func;
}
unsafe extern "C" fn hash_table_enlarge(mut hash_table: *mut HashTable) -> i32 {
    let mut old_table: *mut *mut HashTableEntry = 0 as *mut *mut HashTableEntry;
    let mut old_table_size: u32 = 0;
    let mut old_prime_index: u32 = 0;
    let mut rover: *mut HashTableEntry = 0 as *mut HashTableEntry;
    let mut pair: *mut HashTablePair = 0 as *mut HashTablePair;
    let mut next: *mut HashTableEntry = 0 as *mut HashTableEntry;
    let mut index: u32 = 0;
    let mut i: u32 = 0;
    old_table = (*hash_table).table;
    old_table_size = (*hash_table).table_size;
    old_prime_index = (*hash_table).prime_index;
    (*hash_table).prime_index = ((*hash_table).prime_index).wrapping_add(1);
    (*hash_table).prime_index;
    if hash_table_allocate_table(hash_table) == 0 {
        (*hash_table).table = old_table;
        (*hash_table).table_size = old_table_size;
        (*hash_table).prime_index = old_prime_index;
        return 0 as i32;
    }
    i = 0 as i32 as u32;
    while i < old_table_size {
        rover = *old_table.offset(i as isize);
        while !rover.is_null() {
            next = (*rover).next;
            pair = &mut (*rover).pair;
            index = (((*hash_table).hash_func)
                .expect("non-null function pointer")((*pair).key))
                .wrapping_rem((*hash_table).table_size);
            (*rover).next = *((*hash_table).table).offset(index as isize);
            let ref mut fresh0 = *((*hash_table).table).offset(index as isize);
            *fresh0 = rover;
            rover = next;
        }
        i = i.wrapping_add(1);
        i;
    }
    free(old_table as *mut libc::c_void);
    return 1 as i32;
}
#[no_mangle]
pub unsafe extern "C" fn hash_table_insert(
    mut hash_table: *mut HashTable,
    mut key: HashTableKey,
    mut value: HashTableValue,
) -> i32 {
    let mut rover: *mut HashTableEntry = 0 as *mut HashTableEntry;
    let mut pair: *mut HashTablePair = 0 as *mut HashTablePair;
    let mut newentry: *mut HashTableEntry = 0 as *mut HashTableEntry;
    let mut index: u32 = 0;
    if ((*hash_table).entries)
        .wrapping_mul(3 as i32 as u32)
        .wrapping_div((*hash_table).table_size) > 0 as i32 as u32
    {
        if hash_table_enlarge(hash_table) == 0 {
            return 0 as i32;
        }
    }
    index = (((*hash_table).hash_func).expect("non-null function pointer")(key))
        .wrapping_rem((*hash_table).table_size);
    rover = *((*hash_table).table).offset(index as isize);
    while !rover.is_null() {
        pair = &mut (*rover).pair;
        if ((*hash_table).equal_func)
            .expect("non-null function pointer")((*pair).key, key) != 0 as i32
        {
            if ((*hash_table).value_free_func).is_some() {
                ((*hash_table).value_free_func)
                    .expect("non-null function pointer")((*pair).value);
            }
            if ((*hash_table).key_free_func).is_some() {
                ((*hash_table).key_free_func)
                    .expect("non-null function pointer")((*pair).key);
            }
            (*pair).key = key;
            (*pair).value = value;
            return 1 as i32;
        }
        rover = (*rover).next;
    }
    newentry = malloc(::core::mem::size_of::<HashTableEntry>() as u64)
        as *mut HashTableEntry;
    if newentry.is_null() {
        return 0 as i32;
    }
    (*newentry).pair.key = key;
    (*newentry).pair.value = value;
    (*newentry).next = *((*hash_table).table).offset(index as isize);
    let ref mut fresh1 = *((*hash_table).table).offset(index as isize);
    *fresh1 = newentry;
    (*hash_table).entries = ((*hash_table).entries).wrapping_add(1);
    (*hash_table).entries;
    return 1 as i32;
}
#[no_mangle]
pub unsafe extern "C" fn hash_table_lookup(
    mut hash_table: *mut HashTable,
    mut key: HashTableKey,
) -> HashTableValue {
    let mut rover: *mut HashTableEntry = 0 as *mut HashTableEntry;
    let mut pair: *mut HashTablePair = 0 as *mut HashTablePair;
    let mut index: u32 = 0;
    index = (((*hash_table).hash_func).expect("non-null function pointer")(key))
        .wrapping_rem((*hash_table).table_size);
    rover = *((*hash_table).table).offset(index as isize);
    while !rover.is_null() {
        pair = &mut (*rover).pair;
        if ((*hash_table).equal_func)
            .expect("non-null function pointer")(key, (*pair).key) != 0 as i32
        {
            return (*pair).value;
        }
        rover = (*rover).next;
    }
    return 0 as *mut libc::c_void;
}
#[no_mangle]
pub unsafe extern "C" fn hash_table_remove(
    mut hash_table: *mut HashTable,
    mut key: HashTableKey,
) -> i32 {
    let mut rover: *mut *mut HashTableEntry = 0 as *mut *mut HashTableEntry;
    let mut entry: *mut HashTableEntry = 0 as *mut HashTableEntry;
    let mut pair: *mut HashTablePair = 0 as *mut HashTablePair;
    let mut index: u32 = 0;
    let mut result: i32 = 0;
    index = (((*hash_table).hash_func).expect("non-null function pointer")(key))
        .wrapping_rem((*hash_table).table_size);
    result = 0 as i32;
    rover = &mut *((*hash_table).table).offset(index as isize)
        as *mut *mut HashTableEntry;
    while !(*rover).is_null() {
        pair = &mut (**rover).pair;
        if ((*hash_table).equal_func)
            .expect("non-null function pointer")(key, (*pair).key) != 0 as i32
        {
            entry = *rover;
            *rover = (*entry).next;
            hash_table_free_entry(hash_table, entry);
            (*hash_table).entries = ((*hash_table).entries).wrapping_sub(1);
            (*hash_table).entries;
            result = 1 as i32;
            break;
        } else {
            rover = &mut (**rover).next;
        }
    }
    return result;
}
#[no_mangle]
pub unsafe extern "C" fn hash_table_num_entries(
    mut hash_table: *mut HashTable,
) -> u32 {
    return (*hash_table).entries;
}
#[no_mangle]
pub unsafe extern "C" fn hash_table_iterate(
    mut hash_table: *mut HashTable,
    mut iterator: *mut HashTableIterator,
) {
    let mut chain: u32 = 0;
    (*iterator).hash_table = hash_table;
    (*iterator).next_entry = 0 as *mut HashTableEntry;
    chain = 0 as i32 as u32;
    while chain < (*hash_table).table_size {
        if !(*((*hash_table).table).offset(chain as isize)).is_null() {
            (*iterator).next_entry = *((*hash_table).table).offset(chain as isize);
            (*iterator).next_chain = chain;
            break;
        } else {
            chain = chain.wrapping_add(1);
            chain;
        }
    }
}
#[no_mangle]
pub unsafe extern "C" fn hash_table_iter_has_more(
    mut iterator: *mut HashTableIterator,
) -> i32 {
    return ((*iterator).next_entry != 0 as *mut libc::c_void as *mut HashTableEntry)
        as i32;
}
#[no_mangle]
pub unsafe extern "C" fn hash_table_iter_next(
    mut iterator: *mut HashTableIterator,
) -> HashTablePair {
    let mut current_entry: *mut HashTableEntry = 0 as *mut HashTableEntry;
    let mut hash_table: *mut HashTable = 0 as *mut HashTable;
    let mut pair: HashTablePair = {
        let mut init = _HashTablePair {
            key: 0 as *mut libc::c_void,
            value: 0 as *mut libc::c_void,
        };
        init
    };
    let mut chain: u32 = 0;
    hash_table = (*iterator).hash_table;
    if ((*iterator).next_entry).is_null() {
        return pair;
    }
    current_entry = (*iterator).next_entry;
    pair = (*current_entry).pair;
    if !((*current_entry).next).is_null() {
        (*iterator).next_entry = (*current_entry).next;
    } else {
        chain = ((*iterator).next_chain).wrapping_add(1 as i32 as u32);
        (*iterator).next_entry = 0 as *mut HashTableEntry;
        while chain < (*hash_table).table_size {
            if !(*((*hash_table).table).offset(chain as isize)).is_null() {
                (*iterator).next_entry = *((*hash_table).table).offset(chain as isize);
                break;
            } else {
                chain = chain.wrapping_add(1);
                chain;
            }
        }
        (*iterator).next_chain = chain;
    }
    return pair;
}
unsafe extern "C" fn run_static_initializers_hash_table() {
    hash_table_num_primes = (::core::mem::size_of::<[u32; 24]>()
        as u64)
        .wrapping_div(::core::mem::size_of::<i32>() as u64)
        as u32;
}
#[used]
#[cfg_attr(target_os = "linux", link_section = ".init_array")]
#[cfg_attr(target_os = "windows", link_section = ".CRT$XIB")]
#[cfg_attr(target_os = "macos", link_section = "__DATA,__mod_init_func")]
static INIT_ARRAY: [unsafe extern "C" fn(); 1] = [run_static_initializers_hash_table];
